Examples

Three real datasets shipped with the repository, with worked queries against each. The data lives in examples/data/ and is committed to the repo so the examples are reproducible.


Datasets

filetyperowsresolutionspanshape
pressure.csvfloat2885 min24 hBarometric pressure (hPa), diurnal swing around 1013
cpu-load.csvint14401 min24 hCPU utilisation %, quiet overnight, mid-day spike
requests.csvint7201 min12 hPer-minute HTTP request counts, smooth ramp + a burst

Every file uses contiguous, non-overlapping intervals: adjacent rows share a boundary timestamp, so a point lookup always lands inside exactly one interval.


Loading the data

Client-side load (your machine → remote server)

cargo run --release --bin ctl

τ: connect demo 127.0.0.1:7070
τ: CREATE DATABASE metrics
τ: CREATE LENS pressure float
τ: CREATE LENS cpu int
τ: CREATE LENS requests int
τ: load pressure examples/data/pressure.csv
loaded 288 rows into pressure (2 chunks)
τ: load cpu examples/data/cpu-load.csv
loaded 1440 rows into cpu (6 chunks)
τ: load requests examples/data/requests.csv
loaded 720 rows into requests (3 chunks)

Server-side load (file already on server)

τ: COPY LENS cpu FROM "/path/to/examples/data/cpu-load.csv"
OK

Point lookups

Timestamps are in seconds. t=21600 is 06:00, t=43200 is noon (12:00), t=86400 is end-of-day.

τ: AT LENS cpu 43200
VAL i73

τ: AT LENS pressure 43200
VAL f1014.21

τ: AT LENS requests 21600
VAL i1374

Aggregates over a window

τ: REDUCE LENS cpu 0 86400 USING count
VAL i1440                  ← one interval per minute, full 24 hours

τ: REDUCE LENS cpu 0 86400 USING avg
VAL f36.7694444444         ← time-weighted mean

τ: REDUCE LENS cpu 0 86400 USING min
VAL i5

τ: REDUCE LENS cpu 0 86400 USING max
VAL i82

τ: REDUCE LENS pressure 0 86400 USING avg
VAL f1014.1055555555       ← ~1014.1 hPa mean

τ: REDUCE LENS pressure 0 86400 USING min
VAL f1009.76

τ: REDUCE LENS pressure 0 86400 USING max
VAL f1018.54

τ: REDUCE LENS requests 0 43200 USING sum
VAL i904825                ← total requests in the first 12 hours

τ: REDUCE LENS requests 0 43200 USING max
VAL i2095                  ← peak minute (the burst)

Range scan

τ: RANGE LENS cpu 35000 37000
RANGE 34; 35000:35040:i40; 35040:35100:i38; ...; 36960:37000:i47

34 segments because every minute boundary inside the window is a change point. Adjacent segments with identical values are merged automatically; a long flat run produces a single segment.


Range with WHERE filter

τ: RANGE LENS cpu 0 86400 WHERE cpu > 75
RANGE 78; 44340:44400:i76; 44640:44700:i76; ...; 53880:53940:i78

78 segments, all in the mid-day window when the spike pushed CPU above 75%. The filter is a plain expression; any operator (< <= == != >= >, && ||, arithmetic) works.


Derived lenses

A derived lens is a lazy expression over other lenses. Nothing is materialised: every query re-evaluates the expression on the current data.

Rolling 10-minute average

τ: DERIVE LENS cpu_smooth AS avg(cpu, -600, 0)
OK

τ: AT LENS cpu_smooth 43200
VAL f52.3           ← time-weighted mean of cpu over [42600, 43200)

avg(cpu, -600, 0) evaluates at time t as the time-weighted average of cpu over [t-600, t).

Threshold-derived boolean

τ: DERIVE LENS cpu_busy AS cpu > 70
OK

τ: AT LENS cpu_busy 43200
VAL b1              ← true at noon

τ: AT LENS cpu_busy 7200
VAL b0              ← false at 02:00

Range and reduce work on boolean lenses just like any other.

Cross-lens arithmetic

τ: DERIVE LENS req_rate AS requests / 60
OK

τ: AT LENS req_rate 21600
VAL i22             ← ~22 requests/second at 06:00

Rolling baseline anomaly detection

τ: DERIVE LENS cpu_hot AS cpu > avg(cpu, -1800, 0)
OK

τ: AT LENS cpu_hot 43200
VAL b1              ← instantaneous reading is above the 30-minute rolling mean

This is the canonical "is the signal above its own rolling baseline" pattern. Because adjacent same-value segments are merged, you get one segment per state-change rather than one per minute; ideal for alerting.


Reset

# wipe demo state and start fresh
rm -rf /tmp/tau-demo

Docker stack:

cd container && docker compose down -v && docker compose up -d